/* eslint-disable no-console */
const STATE_KEY = 'apiProxyState';
const DEFAULT_STATE = {
  enabled: true,
  rules: []
};
const LOGS_KEY = 'apiProxyLogs';
const MAX_LOGS = 200;

async function getState() {
  const data = await chrome.storage.local.get([STATE_KEY]);
  return data[STATE_KEY] || { ...DEFAULT_STATE };
}

async function setState(next) {
  const curr = await getState();
  const merged = { ...curr, ...next };
  await chrome.storage.local.set({ [STATE_KEY]: merged });
  await broadcastState(merged);
  return merged;
}

async function getLogs() {
  const data = await chrome.storage.local.get([LOGS_KEY]);
  return data[LOGS_KEY] || [];
}

async function pushLog(entry) {
  try {
    const logs = await getLogs();
    logs.push({ ...entry, time: Date.now() });
    const sliced = logs.slice(-MAX_LOGS);
    await chrome.storage.local.set({ [LOGS_KEY]: sliced });
  } catch (e) {
    // ignore
  }
}

async function broadcastState(state) {
  try {
    const tabs = await chrome.tabs.query({});
    await Promise.all(
      tabs.map(async (tab) => {
        try {
          if (!tab.id) return;
          await chrome.tabs.sendMessage(tab.id, { type: 'stateUpdated', payload: state });
        } catch {
          // ignore per-frame delivery; content scripts may not be injected on special pages
        }
      })
    );
  } catch {
    // ignore
  }
}

// Initialize default state on install/activate
chrome.runtime.onInstalled.addListener(async () => {
  const curr = await getState();
  if (!curr || typeof curr.enabled !== 'boolean' || !Array.isArray(curr.rules)) {
    await setState({ ...DEFAULT_STATE });
  } else {
    // ensure broadcast so current tabs receive at least once
    await broadcastState(curr);
  }
});

chrome.runtime.onStartup && chrome.runtime.onStartup.addListener(async () => {
  const curr = await getState();
  await broadcastState(curr);
});

// Message router
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  (async () => {
    switch (msg?.type) {
      case 'getState': {
        const st = await getState();
        sendResponse({ ok: true, data: st });
        return;
      }
      case 'setEnabled': {
        const st = await setState({ enabled: !!msg.enabled });
        sendResponse({ ok: true, data: st });
        return;
      }
      case 'saveRule': {
        const st = await getState();
        const rule = msg.rule || {};
        let rules = Array.isArray(st.rules) ? [...st.rules] : [];
        if (!rule.id) {
          rule.id = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
          rule.enabled = rule.enabled !== false;
          rules.push(rule);
        } else {
          const idx = rules.findIndex((r) => r.id === rule.id);
          if (idx >= 0) rules[idx] = { ...rules[idx], ...rule };
          else rules.push(rule);
        }
        const next = await setState({ rules });
        sendResponse({ ok: true, data: next });
        return;
      }
      case 'deleteRule': {
        const st = await getState();
        const id = msg.id;
        if (!id) {
          sendResponse({ ok: false, error: 'id required' });
          return;
        }
        const rules = (st.rules || []).filter((r) => r.id !== id);
        const next = await setState({ rules });
        sendResponse({ ok: true, data: next });
        return;
      }
      case 'toggleRule': {
        const st = await getState();
        const id = msg.id;
        const enabled = !!msg.enabled;
        const rules = (st.rules || []).map((r) => (r.id === id ? { ...r, enabled } : r));
        const next = await setState({ rules });
        sendResponse({ ok: true, data: next });
        return;
      }
      case 'saveRules': {
        const rules = Array.isArray(msg.rules) ? msg.rules : [];
        const next = await setState({ rules });
        sendResponse({ ok: true, data: next });
        return;
      }
      case 'log': {
        await pushLog({
          tabId: sender.tab?.id,
          frameId: sender.frameId,
          url: msg.url,
          method: msg.method,
          ruleId: msg.ruleId || null,
          event: msg.event,
          note: msg.note || '',
          sample: msg.sample || null
        });
        sendResponse({ ok: true });
        return;
      }
      case 'getLogs': {
        const logs = await getLogs();
        sendResponse({ ok: true, data: logs });
        return;
      }
      case 'deleteLogs': {
        await chrome.storage.local.remove(LOGS_KEY);
        sendResponse({ ok: true });
        return;
      }
      default:
        sendResponse({ ok: false, error: 'unknown message type' });
        return;
    }
  })();
  // keep message channel open for async sendResponse
  return true;
});

// Also forward storage changes to content scripts (content scripts also listen to this)
chrome.storage.onChanged.addListener((changes, area) => {
  if (area === 'local' && changes[STATE_KEY]?.newValue) {
    broadcastState(changes[STATE_KEY].newValue);
  }
});